#!/usr/bin/ruby
#!/usr/local/bin/ruby

require "getoptlong"

RLEX_VERSION = "1.4"

USAGE = <<EOT
rlex #{RLEX_VERSION}, (c) 2002 Harald Grosse

Usage:  rlex [options] infile
Options:
   --output name    (-o)   names ruby source file and the lexer class
   --debug          (-d)   insert debug code to assist lex/yacc
   --insensitive    (-i)   make a case insensitive lexer
   --help           (-h)   show this message
EOT

$yybol = false         # switch for BOL code
$debug = false
$insensitive = false
$classname = "Lexer"
begin
   GetoptLong.new(['--output', '-o', GetoptLong::REQUIRED_ARGUMENT],
                  ['--debug',  '-d', GetoptLong::NO_ARGUMENT],
                  ['--insensitive',  '-i', GetoptLong::NO_ARGUMENT],
                  ['--help',   '-h', GetoptLong::NO_ARGUMENT]).each { |o,a|
      case o
         when "--help";       print USAGE; exit 0;
         when "--output";     $classname = a;
         when "--debug";      $debug = true;       # internal debugging only
         when "--insensitive"; $insensitive = true;
      end
   }
rescue GetoptLong::InvalidOption
   print USAGE
   exit 1
end
if ARGV.length != 1
   print USAGE
   exit 1
end
inpname = ARGV[0] + ""

def mk_lex1()
   $fp.print <<EOT
   @@yy_init = true
   @@yy_start = 1
   @@yyout = @@yyerr = nil
   attr_reader  :yylineno
   def initialize
      @yy_c_buf_p = 0
      @yy_did_buffer_switch_on_eof = false
      @yyfilename = nil
      @yy_lp = 0
   end
   def yylex(parser=nil)
      @yyparser = parser
      yy_current_state = yy_cp = yy_bp = yy_act = 0
      yy_full_match = 0
      if @@yy_init == true
         @@yy_init = false
         @@yyout = $stdout if @@yyout == nil
         @@yyerr = $stderr if @@yyerr == nil
         @@yybase = @@yynext = 0
         YY_BASE.each { |i| @@yybase = i if i > @@yybase }
         YY_NXT.each { |i| @@yynext = i if i > @@yynext }
EOT
   $fp.print <<EOT if $debug != false
puts "YY_BASE=" + @@yybase.to_s
puts "YY_NEXT=" + @@yynext.to_s
EOT
   $fp.print <<EOT
         yy_create_buffer()
         @yylineno = 1
         @yyleng = 0
      end
      @yyin = $stdin if @yyin == nil
      state = :START
      loop do
         case state
            when :START
EOT
   $fp.print <<EOT if $debug != false
puts "state START"
EOT
   $fp.print <<EOT
               yy_cp = @yy_c_buf_p
               @yy_ch_buf[yy_cp] = @yy_hold_char
               yy_bp = yy_cp
               state = :YY_MATCH
               yy_current_state = @@yy_start
EOT
   if $reject == true
      $fp.print <<EOT
               @yy_state_ptr = []
               @yy_state_ptr.push(yy_current_state)
EOT
   end
   $fp.print <<EOT if $yybol == true
               yy_current_state += @yy_at_bol
EOT
   $fp.print <<EOT if $debug != false
puts "   CURR_STATE=" + yy_current_state.to_s
EOT
   $fp.print <<EOT
               next
            when :YY_MATCH
EOT
   $fp.print <<EOT if $debug != false
puts "state YY_MATCH"
EOT
   $fp.print <<EOT
               loop do
                  yy_c = YY_EC[ @yy_ch_buf[yy_cp] ]
EOT
   $fp.print <<EOT if $debug != false
puts "   YY_C =" + yy_c.to_s
puts "   YY_CP=" + yy_cp.to_s +  "   '" + @yy_ch_buf[yy_cp..yy_cp] + "'"
puts "   CURR_STATE=" + yy_current_state.to_s
puts "   YY_ACC=" + YY_ACCEPT[yy_current_state].to_s
EOT
   $fp.print <<EOT
                  if YY_ACCEPT[yy_current_state] != 0
                     @yy_last_accepting_state = yy_current_state
                     @yy_last_accepting_cpos = yy_cp
                  end
                  while YY_CHK[ YY_BASE[yy_current_state] + yy_c] != yy_current_state
                     yy_current_state = YY_DEF[yy_current_state]
                     yy_c = YY_META[yy_c] if yy_current_state > @@yynext
                  end
                  yy_current_state = YY_NXT[ YY_BASE[yy_current_state] + yy_c]
EOT
   $fp.print <<EOT if $debug != false
puts "   NEW CURR_STATE=" + yy_current_state.to_s
EOT
   if $reject == true
      $fp.print <<EOT
                  @yy_state_ptr.push(yy_current_state)
EOT
   end
   $fp.print <<EOT
                  yy_cp += 1
EOT
   $fp.print <<EOT if $debug != false
puts "   NEW YY_CP=" + yy_cp.to_s
puts "   YY_BASE=" + YY_BASE[yy_current_state].to_s
EOT
   $fp.print <<EOT
                  break if YY_BASE[yy_current_state] == @@yybase
               end
               state = :YY_FIND_ACTION
               next
EOT
   if $reject == true
   $fp.print <<EOT
            when :REJECT
               @yy_ch_buf[yy_cp] = @yy_hold_char
               yy_cp = yy_full_match
               @yy_lp += 1
               state = :FIND_RULE
               next
EOT
   end
   $fp.print <<EOT
            when :YY_FIND_ACTION
EOT
   $fp.print <<EOT if $debug != false
puts "state YY_FIND_ACTION"
EOT
   if $reject == true
      $fp.print <<EOT
               yy_current_state = @yy_state_ptr.pop
               @yy_lp = YY_ACCEPT[yy_current_state]
               state = :FIND_RULE
               next
            when :FIND_RULE
               loop do
                  if @yy_lp > 0 && @yy_lp < YY_ACCEPT[yy_current_state + 1]
                     yy_act = YY_ACCLIST[@yy_lp]
                     yy_full_match = yy_cp
                     break
                  end
                  yy_cp -= 1
                  yy_current_state = @yy_state_ptr.pop
                  @yy_lp = YY_ACCEPT[yy_current_state]
               end
               state = :YY_FIND_ACTION_END
               next
EOT
   else
      $fp.print <<EOT
               yy_act = YY_ACCEPT[yy_current_state]
               if yy_act == 0
                  yy_cp = @yy_last_accepting_cpos
                  yy_current_state = @yy_last_accepting_state
                  yy_act = YY_ACCEPT[yy_current_state]
               end
               state = :YY_FIND_ACTION_END
               next
EOT
   end
   $fp.print <<EOT
            when :YY_FIND_ACTION_END
               @yytext = yy_bp
               @yyleng = yy_cp - yy_bp
               @yy_hold_char = @yy_ch_buf[yy_cp]
               if yy_cp == @yy_ch_buf.length
                  @yy_ch_buf += "\0"
               else
                  @yy_ch_buf[yy_cp] = "\0"
               end
               @yy_c_buf_p = yy_cp
               state = :DO_ACTION
               next
            when :DO_ACTION
EOT
   $fp.print <<EOT if $debug != false
puts "state YY_DO_ACTION"
puts "   YY_ACT=" + yy_act.to_s
EOT
   $fp.print <<EOT
               case yy_act
                  when 0
                     @yy_ch_buf[yy_cp] = @yy_hold_char
                     yy_cp = @yy_last_accepting_cpos
                     yy_current_state = @yy_last_accepting_state
                     state = :YY_FIND_ACTION
                     next
EOT
end
def mk_lex2()
   $fp.print <<EOT
                     # @@yyout.printf "%-*.*s", @yyleng, @yyleng, @yy_ch_buf[@yytext..-1]
                     state = :START
                     next
                  when YY_END_OF_BUFFER + INITIAL + 1
 # sidorovis changes: returning -1 on EOF
                     return [-1, nil]
EOT
   $smark.each { |m|
   $fp.print <<EOT
                  when YY_END_OF_BUFFER + #{m} + 1
                     return 0
EOT
   }
   $fp.print <<EOT
                  when YY_END_OF_BUFFER
                     yy_amount_of_matched_text = (yy_cp - @yytext) - 1
                     @yy_ch_buf[yy_cp] = @yy_hold_char
                     @yy_buffer_status = YY_BUFFER_NORMAL if @yy_buffer_status == YY_BUFFER_NEW
                     if @yy_c_buf_p <= @yy_n_chars
                        @yy_c_buf_p = @yytext + yy_amount_of_matched_text
                        yy_current_state = yy_get_previous_state()
                        yy_next_state = yy_try_NUL_trans(yy_current_state)
                        yy_bp = @yytext + YY_MORE_ADJ 
                        if @yy_next_state != 0
                           @yy_c_buf_p += 1
                           yy_cp = @yy_c_buf_p
                           yy_current_state = yy_next_state
                           state = :YY_MATCH
                           next
                        else
                           yy_cp = @yy_c_buf_p
                           state = :YY_FIND_ACTION
                           next
                        end
                     else
                        case yy_get_next_buffer()
                           when EOB_ACT_END_OF_FILE
                              @yy_did_buffer_switch_on_eof = false
                              if yywrap() != 0
                                 @yy_c_buf_p = @yytext + YY_MORE_ADJ
                                 yy_act = YY_END_OF_BUFFER + ((@@yy_start - 1) / 2) + 1
                                 state = :DO_ACTION
                                 next
                              else
                                 yyrestart() if @yy_did_buffer_switch_on_eof == false
                                 state = :START
                                 next
                              end
                           when EOB_ACT_CONTINUE_SCAN
                              @yy_c_buf_p = @yytext + yy_amount_of_matched_text
                              yy_current_state = yy_get_previous_state()
                              yy_cp = @yy_c_buf_p
                              yy_bp = @yytext + YY_MORE_ADJ
                              state = :YY_MATCH
                              next
                           when EOB_ACT_LAST_MATCH
                              @yy_c_buf_p = @yy_n_chars
                              yy_current_state = yy_get_previous_state()
                              yy_cp = @yy_c_buf_p
                              yy_bp = @yytext + YY_MORE_ADJ
                              state = :YY_FIND_ACTION
                              next
                           else
                              state = :START
                              next
                        end
                     end
                  else
                     yyerror("fatal internal error -- no action found")
                     exit 2
               end # case yy_act
         end # case state
         state = :START
      end # loop
   end # yylex
   private
   def yy_get_next_buffer
      if @yy_fill_buffer == 0
         return EOB_ACT_END_OF_FILE if @yy_c_buf_p - @yytext - YY_MORE_ADJ == 1
         return EOB_ACT_LAST_MATCH
      end
      number_to_move = @yy_c_buf_p - @yytext - 1
      for i in 0..number_to_move do
         @yy_ch_buf[i] = @yy_ch_buf[@yytext + i]
      end
      if @yy_buffer_status == YY_BUFFER_EOF_PENDING
         @yy_n_chars = 0
      else
         num_to_read = @yy_buf_size - number_to_move - 1
         num_to_read = YY_READ_BUF_SIZE if num_to_read > YY_READ_BUF_SIZE
         case @yyin.class.to_s
            when "File"
               input = @yyin.read(num_to_read)
            when "String"
 # sidorovis: correcly working with a strings
               input, @yyin = @yyin, ""
            when "Array"
               input, @yyin = @yyin.to_s, ""
         end
         if input == nil
            @yy_n_chars = 0
         else
            @yy_n_chars = input.length
            @yy_ch_buf[number_to_move..-1] = input + "\0\0"
         end
      end
      if @yy_n_chars == 0
         if number_to_move == YY_MORE_ADJ
            ret_val = EOB_ACT_END_OF_FILE
            yyrestart()
         else
            ret_val = EOB_ACT_LAST_MATCH
            @yy_buffer_status = YY_BUFFER_EOF_PENDING
         end
      else
         ret_val = EOB_ACT_CONTINUE_SCAN
      end
      @yy_n_chars += number_to_move
      @yy_ch_buf[@yy_n_chars] = "\0"
      @yy_ch_buf[@yy_n_chars + 1] = "\0"
      @yytext = 0
      ret_val
   end
   def yy_get_previous_state
      yy_cp = 0
      yy_current_state = @@yy_start
EOT
   if $reject == true
   $fp.print <<EOT if $yybol == true
      @yy_state_ptr = []
      @yy_state_ptr.push(yy_current_state)
EOT
   end
   $fp.print <<EOT if $yybol == true
      yy_current_state += @yy_at_bol
EOT
   $fp.print <<EOT
      b = @yytext + YY_MORE_ADJ
      e = @yy_c_buf_p
      for yy_cp in b...e do
         yy_c = (@yy_ch_buf[yy_cp] != "\0") ? YY_EC[ @yy_ch_buf[yy_cp] ] : 1
         if YY_ACCEPT[yy_current_state] != 0
             @yy_last_accepting_state = yy_current_state
             @yy_last_accepting_cpos = yy_cp
         end
         while YY_CHK[YY_BASE[yy_current_state] + yy_c] != yy_current_state
            yy_current_state = YY_DEF[yy_current_state]
            yy_c = YY_META[yy_c] if yy_current_state > @@yynext
         end
         yy_current_state = YY_NXT[YY_BASE[yy_current_state] + yy_c]
EOT
   if $reject == true
      $fp.print <<EOT
         @yy_state_ptr.push(yy_current_state)
EOT
   end
   $fp.print <<EOT
      end
      yy_current_state
   end
   def yy_try_NUL_trans(yy_current_state)
      yy_is_jam = 0
      yy_cp = @yy_c_buf_p
      yy_c = 1
      if YY_ACCEPT[yy_current_state] != 0
         @yy_last_accepting_state = yy_current_state
         @yy_last_accepting_cpos = yy_cp
      end
      while YY_CHK[YY_BASE[yy_current_state] + yy_c] != yy_current_state
         yy_current_state = YY_DEF[yy_current_state]
         yy_c = YY_META[yy_c] if yy_current_state > @@yynext
      end
      yy_current_state = YY_NXT[YY_BASE[yy_current_state] + yy_c]
      yy_is_jam = (yy_current_state == @@yynext) ? 1 : 0
EOT
   if $reject == true
      $fp.print <<EOT
      @yy_state_ptr.push(yy_current_state) if yy_is_jam == 0
EOT
   end
   $fp.print <<EOT
      (yy_is_jam != 0) ? 0 : yy_current_state
   end
   def unput(c)
      yy_unput(c, @yytext)
   end
   alias yyunput unput
   def yy_unput(c, yy_bp)
      src = dest = 0
      yy_cp = @yy_c_buf_p
      @yy_ch_buf[yy_cp] = @yy_hold_char
      if yy_cp < 2
         number_to_move = @yy_n_chars + 2
         dest = @yy_buf_size + 2
         src = number_to_move
         while src > 0
            dest -= 1
            src -= 1
            @yy_ch_buf[dest] = @yy_ch_buf[src]
         end
         yy_cp += (dest - src)
         yy_bp += (dest - src)
         @yy_n_chars = @yy_buf_size
         if yy_cp < 2
            yyerror("flex scanner push-back overflow")
            exit 2
         end
      end
      yy_cp -= 1
      @yy_ch_buf[yy_cp] = c
      @yytext = yy_bp
      @yy_hold_char = @yy_ch_buf[yy_cp]
      @yy_c_buf_p = yy_cp
   end
   def yy_input(cnt, pos, nor)
      c = 0
      @yy_ch_buf[@yy_c_buf_p] = @yy_hold_char
      if @yy_ch_buf[@yy_c_buf_p] == 0
         if @yy_c_buf_p < @yy_n_chars
            @yy_ch_buf[@yy_c_buf_p] = "\0"
         else
            offset = @yy_c_buf_p - @yytext
            @yy_c_buf_p += 1
            act = yy_get_next_buffer()
            loop do
               case act
                  when EOB_ACT_LAST_MATCH
                     yyrestart()
                     act = EOB_ACT_END_OF_FILE
                  when EOB_ACT_END_OF_FILE
                     return EOF if yywrap() != 0
                     yyrestart() if @yy_did_buffer_switch_on_eof == true
                     return yy_input()
                  when EOB_ACT_CONTINUE_SCAN
                     @yy_c_buf_p = @yytext + offset
                     break
               end
            end
         end
      end
      c = @yy_ch_buf[@yy_c_buf_p]
      @yy_ch_buf[@yy_c_buf_p] = "\0"
      @yy_c_buf_p += 1
      @yy_hold_char = @yy_ch_buf[@yy_c_buf_p]
      @yy_at_bol = 1 if c == 10
      c
   end
   def yyrestart
      yy_init_buffer()
      yy_load_buffer_state()
   end
   def yy_load_buffer_state
EOT
   $fp.print <<EOT if $debug != false
puts "YY_LOAD_BUFFER_STATE"
EOT
   $fp.print <<EOT
      @yy_c_buf_p = @yy_ch_buf_pos
      @yytext = @yy_c_buf_p
      @yy_hold_char = @yy_ch_buf[@yy_c_buf_p]
   end
   def yy_create_buffer
EOT
   $fp.print <<EOT if $debug != false
puts "YY_CREATE_BUFFER"
EOT
   $fp.print <<EOT
      @yy_ch_buf = ""
      @yy_buf_size = 16384
      yy_init_buffer()
      @yy_last_accepting_state = 0
      @yy_last_accepting_cpos = 0
   end
   def yy_init_buffer
EOT
   $fp.print <<EOT if $debug != false
puts "YY_INIT_BUFFER"
EOT
   $fp.print <<EOT
      yy_flush_buffer()
      @yy_fill_buffer = 1
   end
   def yy_flush_buffer
      @yy_n_chars = 0
      @yy_ch_buf = "\0"
      @yy_ch_buf += "\0"
      @yy_ch_buf_pos = 0
      @yy_at_bol = 1
      @yy_buffer_status = YY_BUFFER_NEW
      yy_load_buffer_state()
   end
   def yytext
      a = @yytext
      e = @yytext + @yyleng
      e -= 1 if @yy_ch_buf[e..e] <= "\2"
      @yy_ch_buf[a..e]
   end
   def yyin=(val)
      @yyin = val
   end
   def yyout=(val)
      @@yyout = val
   end
   def yyerr=(val)
      @@yyerr = val
   end
   def yyerror(mess)
      if @yyin.class == File && @yyfilename != nil
         @@yyerr.print "`\#\{@yyfilename}' "
      else
         @@yyerr.print "`\#\{@yyin.class}' "
      end
      @@yyerr.print "line \#\{@yylineno}: \#\{mess}"
      m = @yy_ch_buf[@yytext..-1]
      m = $1 if m =~ /(.+)\\n/o
      @@yyerr.print ", near `\#\{m}'" if @yy_ch_buf.length > @yytext
      @@yyerr.puts
   end
   def yywrap
      1
   end
   def filename
      @yyfilename
   end
   def filename=(val)
      @yyfilename = val
   end
   public   :yytext, :yyin=, :yyout=, :yyerr=, :yyerror, :yywrap,
            :filename, :filename=
end # class lexer
EOT
end

# remove from file.rl ruby items, because lex will get confused
inp = File.open(inpname, "r")
rl = inp.read
inp.close
# exchange @ by {RA}
rl.gsub!(/\@/, "{RA}")

# write the code to temporary file for lex
tmpfile = "temp.#{$$}.l"
tmp = File.open(tmpfile, "w")
tmp.write(rl)
tmp.close

# let lex compile this code to tmpfile.c
%x{lex #{$insensitive ? "-i" : nil} -o#{tmpfile}.c #{tmpfile}}
#%x{wine lex #{$insensitive ? "-i" : nil} -o#{tmpfile}.c #{tmpfile}}
File.delete(tmpfile)

# generiere output ruby code
# generate ruby code from tmpfile.c
tmp = File.open(tmpfile + ".c", "r")
# $fp = $stdout
$fp = File.open("#{$classname}.rb", "w")
# start, class definitions
$fp.printf <<EOT
#!/usr/bin/ruby

class #{$classname}
   class LexError < StandardError; end

EOT
state = :START
nested = 0
$reject = false
$smark = []
# parse the lex output file
tmp.each_line { |line|
   # exchange previously changed ruby items to there origin
   line.gsub!(/\{RA\}/, "@")
   # evaluation, state marks the different sections of lex output
   case state
      when :START
         # change to state DEFINE
         if line =~ /^#define YY_NUM_RULES \d+/o
            state = :DEFINE
            redo
         end
         # mark if there is a REJECT
         if line =~ /^#define YY_USES_REJECT/o
            $reject = true
            next
         end
         # take over some specific defines
         if line =~ /^#define\s+(YY_READ_BUF_SIZE|YY_BUFFER_NEW|YY_BUFFER_NORMAL|YY_BUFFER_EOF_PENDING|EOB_ACT_LAST_MATCH|EOB_ACT_CONTINUE_SCAN|EOB_ACT_END_OF_FILE)\s+(\d+)/o
            $fp.printf "   %s = %s\n", $1, $2
            next
         end
      when :DEFINE
         # change to state TABLE
         if line =~ /^static\s+yyconst\s+/o
            state = :TABLE
            redo
         end
         # take over #defines for the tables
         if line =~ /^#define\s+(\S+)\s+(-?\d+)/o
            $fp.printf "   %s = %s\n", $1, $2
            next
         end
         # ignore rest of lines
      when :TABLE
         # ignore lines without any character
         if line !~ /\S/;    next;   end
         # take over tables with short/ints
         if line =~ /^static\s+yyconst\s+(short|short int|int)\s+(yy_acclist|yy_accept|yy_ec|yy_meta|yy_base|yy_def|yy_nxt|yy_chk)\[(\d+)\]\s+=/o
            $fp.printf "   %s = [\n", $2.upcase
            state = :INTABLE
            next
         end
         # next state
         state = :DEFAULT
      when :INTABLE
         # change to state TABLE
         if line =~ /^\s+\}\s+\;/o
            state = :TABLE
            $fp.puts "   ]"
            next
         end
         # remove the block open mark
         line = "     " + $' if line =~ /\s+\{/o
         # take over all lines of the table
         $fp.puts line
      when :DEFAULT
         # change to state CODELEX
         if line =~ /^YY_DECL/o
            state = :CODELEX
            mk_lex1()
            next
         end
         # change to state SRCHRUBY
         if line =~ /^#if YY_MAIN/o
            state = :SRCHRUBY
            mk_lex2()
            next
         end
         # change to state TOKENS
         if line =~ /^#line 1\s+/o
            state = :TOKENS
            next
         end
         # check code for BOL
         if line =~ /^#define\s+YY_RULE_SETUP/o
            state = :RULESETUP
            next
         end
         # take over some specific defines
         if line =~ /^#define\s+(YY_MORE_ADJ|YY_READ_BUF_SIZE)\s+(\d+)/o
            $fp.printf "   %s = %s\n", $1, $2
            next
         end
         # ignore rest of lines
      when :RULESETUP
         # change to state DEFAULT
         if line =~ /\s+YY_USER_ACTION/o
            state = :DEFAULT
            next
         end
         # activate BOL-code
         $yybol = true
      when :TOKENS
         # change to state DEFAULT
         if line =~ /^#ifndef YY_SKIP_YYWRAP/o
            state = :DEFAULT
            next
         end
         # take over token defines
         if line =~ /^#define\s+(\S+)\s+(\d+)/o
            $fp.printf "   %s = %s\n", $1, $2
            next
         end
         # ignore empty lines
         if line !~ /\S/; next; end
         # ignore comments
         next if line[0..0] == "#" or line[0..1] == "/*" or line[0..1] == " *"
         # all other lines are part of class Lexer
         $fp.puts line
      when :CODELEX
         # change to state CASELEX
         if line =~ /^case\s+(\d+):/o
            state = :CASELEX
            nested = 0
            $fp.puts " " * 18 + "when #{$1}"
            next
         end
         # ignore all lines
         next
      when :CASELEX
         # change to state DEFAULT
         if line =~ /^ECHO;/o
            state = :DEFAULT
            next
         end
         # search for additional code
         if line =~ /\*yy_cp\s+=\s+yy_hold_char/o
            $fp.puts " " * 21 + "@yy_ch_buf[yy_cp] = @yy_hold_char"
            next
         end
         if line =~ /yy_c_buf_p\s+=\s+yy_cp\s+-=\s+1/o
            $fp.puts " " * 21 + "@yy_c_buf_p = (yy_cp -= 1)"
            next
         end
         # search for block mark, which opens ruby code, and remove it
         if line =~ /\s*\{/
            line.gsub!(/\{/, "")
            state = :CODECASE_IN
            nested = 0
            $fp.puts " " * 21 + "@yy_at_bol = (@yy_ch_buf[@yytext + @yyleng - 1] == 10) ? 1 : 0 if @yyleng > 0" if $yybol == true
            redo
         end
         # if there is only a single ';', then do nothing
         if line =~ /\;/
            state = :CODELEX
            $fp.puts " " * 21 + "@yy_at_bol = (@yy_ch_buf[@yytext + @yyleng - 1] == 10) ? 1 : 0 if @yyleng > 0" if $yybol == true
            next
         end
         # ignore all other lines
         next
      when :CODECASE_IN
         # increment variable nested, if additional block opens in the block
         nested += 1 if line =~ /\s*\{/
         # search for block close mark
         if line =~ /\s*\}\s*/
            # test for end of code block
            if nested == 0
               state = :CODELEX
               line = $`
            else
               nested -= 1
            end
         end
         # strip white spaces at beginning and end of line
         line.strip!
         # ignore empty lines
         if line !~ /\S/; next; end
         # ist there an REJECT?
         if line =~ /(.*)REJECT(.*)/o
            line =  $1 + "state = :REJECT; next" + $2
         end
         # remember all additonal start marks other than INITIAL
         if line =~ /^BEGIN\((.+)\);/o
            $fp.puts " " * 21 + "@@yy_start = 1 + 2 * #{$1}"
            $smark.push($1) if $1 != "INITIAL"
            next
         end
         # change return(x)
         if line =~ /^return\((.+)\);/o
            $fp.puts " " * 21 + "return #{$1}"
            next
         end
         # puts rest of line
         $fp.puts " " * 21 + "#{line}"
      when :SRCHRUBY
         # change to state CODERUBY
         if line =~ /^#line\s+\d+/o
            state = :CODERUBY
            next
         end
         # ignore lines
     when :CODERUBY
         # take over all manual coded ruby source
         $fp.puts line
   end
}

# remove lex output file
$fp.close
tmp.close
File.delete(tmpfile + ".c")
